﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Documents;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Controls.Primitives;

namespace Kokomo.Controls
{
	public class WatermarkAdorner : Adorner
	{
		static WatermarkAdorner()
		{
			DefaultStyleKeyProperty.OverrideMetadata(typeof(WatermarkAdorner), new FrameworkPropertyMetadata(typeof(WatermarkAdorner)));
			IsHitTestVisibleProperty.OverrideMetadata(typeof(WatermarkAdorner), new FrameworkPropertyMetadata(false));
		}

		internal WatermarkAdorner(UIElement adornedElement)
			: base(adornedElement)
		{
			this._presenter = new ContentPresenter();
			this._presenter.SetBinding(ContentPresenter.ContentProperty, new Binding() { Source = adornedElement, Path = new PropertyPath(WatermarkService.WatermarkContentProperty) });
			this._presenter.SetBinding(WatermarkAdorner.ContentTemplateProperty, new Binding() { Source = this, Path = new PropertyPath(WatermarkAdorner.ContentTemplateProperty) });

			this.AddLogicalChild(this._presenter);
			this.AddVisualChild(this._presenter);

			adornedElement.IsKeyboardFocusWithinChanged += new DependencyPropertyChangedEventHandler(AdornedElement_IsKeyboardFocusWithinChanged);

			this.AdornedTextBox = adornedElement as TextBox;

			//adornedElement.LayoutUpdated += new EventHandler(AdornedElement_LayoutUpdated);
		}

		void AdornedElement_LayoutUpdated(object sender, EventArgs e)
		{
			this.InvalidateMeasure();
			this.InvalidateVisual();
		}

		void AdornedElement_IsKeyboardFocusWithinChanged(object sender, DependencyPropertyChangedEventArgs e)
		{
			this.UpdateComputedVisibility();
		}

		private ContentPresenter _presenter;

		private TextBox _adornedTextBox;
		private TextBox AdornedTextBox
		{
			get { return this._adornedTextBox; }
			set
			{
				if (this._adornedTextBox == value) return;

				if (this._adornedTextBox != null)
				{
					this._adornedTextBox.TextChanged -= new TextChangedEventHandler(AdornedTextBox_TextChanged);
				}
				this._adornedTextBox = value;
				if (value != null)
				{
					value.TextChanged += new TextChangedEventHandler(AdornedTextBox_TextChanged);
				}
			}
		}

		void AdornedTextBox_TextChanged(object sender, TextChangedEventArgs e)
		{
			this.UpdateComputedVisibility();
		}

		protected override Size MeasureOverride(Size constraint)
		{
			Size adornedSize = this.AdornedElement.RenderSize;
			this._presenter.Measure(adornedSize);
			return adornedSize;
		}

		//protected override Size MeasureOverride(Size constraint)
		//{
		//    this._presenter.Measure(constraint);
		//    return this._presenter.DesiredSize;
		//}

		protected override Size ArrangeOverride(Size finalSize)
		{
			Rect adornerRect = LayoutInformation.GetLayoutSlot((FrameworkElement)this.AdornedElement);
			this._presenter.Arrange(new Rect(new Point(), finalSize));
			return this._presenter.RenderSize;
		}

		protected override int VisualChildrenCount
		{
			get { return 1; }
		}

		protected override Visual GetVisualChild(int index)
		{
			return this._presenter;
		}
		//public object Content
		//{
		//    get { return (object)GetValue(ContentProperty); }
		//    set { SetValue(ContentProperty, value); }
		//}

		//// Using a DependencyProperty as the backing store for Content.  This enables animation, styling, binding, etc...
		//public static readonly DependencyProperty ContentProperty = ContentPresenter.ContentProperty.AddOwner(typeof(WatermarkAdorner));

		public DataTemplate ContentTemplate
		{
			get { return (DataTemplate)GetValue(ContentTemplateProperty); }
			set { SetValue(ContentTemplateProperty, value); }
		}

		// Using a DependencyProperty as the backing store for ContentTemplate.  This enables animation, styling, binding, etc...
		public static readonly DependencyProperty ContentTemplateProperty = ContentPresenter.ContentTemplateProperty.AddOwner(typeof(WatermarkAdorner));



		public Visibility ComputedVisibility
		{
			get { return (Visibility)GetValue(ComputedVisibilityProperty); }
			private set { SetValue(ComputedVisibilityPropertyKey, value); }
		}

		// Using a DependencyProperty as the backing store for ComputedVisibility.  This enables animation, styling, binding, etc...
		private static readonly DependencyPropertyKey ComputedVisibilityPropertyKey =
			DependencyProperty.RegisterReadOnly("ComputedVisibility", typeof(Visibility), typeof(WatermarkAdorner), new UIPropertyMetadata(Visibility.Hidden));
		public static readonly DependencyProperty ComputedVisibilityProperty = ComputedVisibilityPropertyKey.DependencyProperty;

		private void UpdateComputedVisibility()
		{
			bool isVisible =
				(!this.AdornedElement.IsKeyboardFocused)
				&& (
					(this.AdornedTextBox == null)
					|| (string.IsNullOrEmpty(this.AdornedTextBox.Text))
					);

			Visibility visibility = isVisible ? Visibility.Visible : System.Windows.Visibility.Hidden;
			this.ComputedVisibility = visibility;
			this._presenter.Visibility = visibility;
		}
	}
}
